home *** CD-ROM | disk | FTP | other *** search
- #include <dos.h>
- #include <dpmi.h>
- #include <pc.h>
- #include "gccint8.h"
-
- #define IRQ0 0x8
- #define PIT0 0x40
- #define PIT1 0x41
- #define PIT2 0x42
- #define PITMODE 0x43
- #define PITCONST 1193180L
- #define PIT0DEF 18.2067597
- #define KBCTRL 0x61
- #define NEW8H 1
-
- static float tick_per_ms = 0.0182068;
- static float ms_per_tick = 54.9246551;
- static float freq8h = 18.2067597;
- static unsigned char flag8h = 0;
- static _go32_dpmi_seginfo rm_old_handler,
- rm_new_handler,
- pm_old_handler,
- pm_new_handler;
- static _go32_dpmi_registers r,
- r1;
-
- volatile int counter_8h;
- volatile int counter_reset;
- volatile unsigned long int ticks_8h;
-
- void init8h(unsigned int Hz)
- {
- unsigned int pit0_set,
- pit0_value;
-
- if (flag8h != NEW8H) {
- disable();
-
- _go32_dpmi_get_protected_mode_interrupt_vector(8, &pm_old_handler);
- pm_new_handler.pm_offset = (int) pm_new8h;
- pm_new_handler.pm_selector = _go32_my_cs();
- _go32_dpmi_chain_protected_mode_interrupt_vector(8, &pm_new_handler);
-
- _go32_dpmi_get_real_mode_interrupt_vector(8, &rm_old_handler);
- rm_new_handler.pm_offset = (int) rm_new8h;
- _go32_dpmi_allocate_real_mode_callback_iret(&rm_new_handler, &r1);
- _go32_dpmi_set_real_mode_interrupt_vector(8, &rm_new_handler);
-
- outportb(PITMODE, 0x36);
- pit0_value = PITCONST / Hz;
- pit0_set = (pit0_value & 0x00ff);
- outportb(PIT0, pit0_set);
- pit0_set = (pit0_value >> 8);
- outportb(PIT0, pit0_set);
-
- enable();
-
- flag8h = NEW8H;
- freq8h = Hz;
- counter_8h = 0;
- counter_reset = freq8h / PIT0DEF;
- tick_per_ms = freq8h / 1000;
- ms_per_tick = 1000 / freq8h;
- }
- }
-
- void quit8h(void)
- {
- unsigned int pit0_set,
- pit0_value;
- unsigned long tick;
- char *cmostime;
-
- if (flag8h == NEW8H) {
-
- disable();
-
- outportb(PITMODE, 0x36);
- outportb(PIT0, 0x00);
- outportb(PIT0, 0x00);
-
- _go32_dpmi_set_real_mode_interrupt_vector(8, &rm_old_handler);
- _go32_dpmi_set_protected_mode_interrupt_vector(8, &pm_old_handler);
- _go32_dpmi_free_real_mode_callback(&rm_new_handler);
-
- enable();
-
- cmostime = get_cmostime();
- tick = PIT0DEF *
- (
- (((float) *cmostime) * 3600) +
- (((float) *(cmostime + 1)) * 60) +
- (((float) *(cmostime + 2)))
- );
- biostime(1, tick);
-
- flag8h = 0;
- freq8h = PIT0DEF;
- counter_reset = freq8h / PIT0DEF;
- tick_per_ms = freq8h / 1000;
- ms_per_tick = 1000 / freq8h;
- }
- }
-
- void rm_new8h(void)
- {
- ticks_8h++;
- counter_8h++;
-
- if (counter_8h == counter_reset) {
- counter_8h = 0;
- memset(&r, 0, sizeof(r));
- r.x.cs = rm_old_handler.rm_segment;
- r.x.ip = rm_old_handler.rm_offset;
- r.x.ss = r.x.sp = 0;
- _go32_dpmi_simulate_fcall_iret(&r);
- /* Note. You should use "r.x.cs = 0xf000; r.x.ip = 0xfea5;" instead
- * of "r.x.cs = rm_old_handler.rm_segment; r.x.ip =
- * rm_old_handler.rm_offset;" if your gcc version is older than
- * 2.6.3. This is because of a bug in gcc 2.6.0. PCTIMER for gcc was
- * first developed under gcc 2.6.0, and it was found that the
- * following instructions: "r.x.cs = rm_old_handler.rm_segment;
- * r.x.ip = rm_old_handler.rm_offset; r.x.ss = r.x.sp = 0;
- * _go32_dpmi_simulate_fcall_iret(&r);" could not call
- * rm_old_handler.rm_segment:rm_old_handler.rm_offset correctly.
- * Therefore, my solution in PCTIMER 1.1 was to call f000:fea5, which
- * is the default handler of int 8h in IBM PC and fully compatible
- * BIOSes. Since the bug has been fixed in gcc 2.6.3, the
- * "rm_new8h" handler should also be revised. */
- } else {
- outportb(0x20, 0x20);
- }
- }
-
- void pm_new8h(void)
- {
- ticks_8h++;
- counter_8h++;
-
- if (counter_8h == counter_reset) {
- counter_8h = 0;
- } else {
- outportb(0x20, 0x20);
- }
- }
-
- unsigned long time8h(unsigned long start, unsigned long stop)
- {
- unsigned long duration,
- millisec;
-
- if (stop < start)
- return 0;
- else {
- duration = stop - start;
- millisec = duration * ms_per_tick;
- return millisec;
- }
- }
-
- void delay8h(unsigned int delayms)
- {
- unsigned long int delaybegin = 0;
- unsigned long int delayend = 0;
- unsigned int delaytick;
-
- delaytick = delayms * tick_per_ms;
-
- if (flag8h == NEW8H)
- delaybegin = ticks_8h;
- else
- delaybegin = biostime(0, 0);
-
- do {
- if (flag8h == NEW8H)
- delayend = ticks_8h;
- else
- delayend = biostime(0, 0);
- } while ((delayend - delaybegin) < delaytick);
- }
-
- void sound8h(int freq, int duration)
- {
- int byte;
- unsigned int freq1;
-
- freq1 = PITCONST / freq;
- outportb(PITMODE, 0xb6);
- byte = (freq1 & 0xff);
- outportb(PIT2, byte);
- byte = (freq1 >> 8);
- outportb(PIT2, byte);
- byte = inportb(KBCTRL);
- outportb(KBCTRL, (byte | 3));
-
- delay8h(duration);
- outportb(KBCTRL, (byte & 0xfc));
- }
-
- char *get_cmostime(void)
- {
- char *buff;
- static char buffer[6];
- char ch;
-
- buff = buffer;
- memset(&r, 0, sizeof(r));
- r.h.ah = 0x02;
- _go32_dpmi_simulate_int(0x1a, &r);
-
- ch = r.h.ch;
- buffer[0] = (char) ((int) (ch & 0x0f) + (int) ((ch >> 4) & 0x0f) * 10);
- ch = r.h.cl;
- buffer[1] = (char) ((int) (ch & 0x0f) + (int) ((ch >> 4) & 0x0f) * 10);
- ch = r.h.dh;
- buffer[2] = (char) ((int) (ch & 0x0f) + (int) ((ch >> 4) & 0x0f) * 10);
- buffer[3] = r.h.dl;
- buffer[4] = (char) (r.x.flags & 0x0001);
- buffer[5] = 0x00;
-
- return (buff);
- }